package orm

import (
	"encoding/json"
	"errors"
	"fmt"
	"gluenet/pkg/apis"
	"gluenet/pkg/gerrors"
	"gluenet/pkg/meta"
	"gluenet/pkg/ops/dbi"
	"strings"
	"time"
)

func UpdateStatus(c dbi.GlueDB, platform string, guid string) error {
	//end := time.Now().Unix()
	//start := end - 60

	switch platform {
	//case apis.PlatfromGluenets:
	//	var res *meta.ScheduleResults
	//	if err := c.ScheduleResultGet(guid, &res); err != nil {
	//		return fmt.Errorf("get schedule result %v", err)
	//	}
	//	m, err := meta.DeCodeScheduleMaps(res.ScheduleMap)
	//	if err != nil {
	//		return fmt.Errorf("decode schedule map %v", err)
	//	}
	//
	//	var cells = glue.Cells{
	//		Cells: make(map[string]glue.Cell),
	//	}
	//	var agentCells = make(map[string]glue.Cells)
	//	for service, agentGuid := range m {
	//		var data = []map[string]interface{}{}
	//		if err = c.GetStatus(fmt.Sprintf(metrics_sql.GluenetsContainerState, agentGuid, guid, service, start, end), &data); err != nil {
	//			return fmt.Errorf("get data")
	//		}
	//
	//		if _, ok := agentCells[agentGuid]; !ok {
	//			agentCells[agentGuid] = glue.Cells{
	//				Cells: make(map[string]glue.Cell),
	//			}
	//		}
	//
	//		//fmt.Printf("\nagentGuid %v guid %v service %v data %v\n", agentGuid, guid, service, data)
	//
	//		if len(data) == 0 {
	//			cells.Cells[service] = glue.Cell{
	//				Name:  service,
	//				State: meta.StateNotReady,
	//				Guid:  agentGuid,
	//			}
	//
	//			agentCells[agentGuid].Cells[strings.Join([]string{guid, service}, "_")] = glue.Cell{
	//				Name:  service,
	//				State: meta.StateNotReady,
	//				Guid:  guid,
	//			}
	//		} else {
	//			container := data[0]["container"].(string)
	//			state := data[0]["_value"].(string)
	//			cells.Cells[container] = glue.Cell{
	//				Name:  container,
	//				State: state,
	//				Guid:  agentGuid,
	//			}
	//			//fmt.Printf("\nagentGuid %v guid %v service %v data %v\n", agentGuid, guid, service, data)
	//			agentCells[agentGuid].Cells[strings.Join([]string{guid, service}, "_")] = glue.Cell{
	//				Name:  service,
	//				State: state,
	//				Guid:  guid,
	//			}
	//			//fmt.Printf("\ncells %v\n", agentCells)
	//		}
	//
	//	}
	//	bts, _ := json.Marshal(cells)
	//
	//	StrCell := string(bts)
	//	if _, err := c.MetaDB().Exec(`insert into instance_runtime (guid,platform,cells) values (?,?,?) on duplicate key update cells=?`, guid, platform, StrCell, StrCell); err != nil {
	//		return fmt.Errorf("save instance runtime %v", err)
	//	}
	//
	//	//fmt.Printf("\n\n agent Cells %v", agentCells)
	//
	//	for agentGuid, ac := range agentCells {
	//		var oldcells []meta.AgentRunTime
	//		if err = c.MetaDB().SQL(`select * from agent_runtime where guid=?`, agentGuid).Find(&oldcells); err != nil {
	//			return fmt.Errorf("save agent runtime %v", err)
	//		}
	//		var bts2 []byte
	//		var counts int
	//		if len(oldcells) != 0 {
	//			var gcell glue.Cells
	//			if err = json.Unmarshal([]byte(oldcells[0].Cells), &gcell); err != nil {
	//				return err
	//			}
	//			for k, v := range ac.Cells {
	//				gcell.Cells[k] = v
	//			}
	//			bts2, _ = json.Marshal(gcell)
	//			counts = len(gcell.Cells)
	//		} else {
	//			bts2, _ = json.Marshal(ac)
	//			counts = len(ac.Cells)
	//		}
	//		agentStrCell := string(bts2)
	//
	//		//fmt.Printf("\n %v %v %v \n", agentGuid, counts, agentStrCell)
	//
	//		if _, err := c.MetaDB().Exec(`insert into agent_runtime (guid,counts,cells) values (?,?,?) on duplicate key update counts=?,cells=?`, agentGuid, counts, agentStrCell, counts, agentStrCell); err != nil {
	//			return fmt.Errorf("save agent runtime %v", err)
	//		}
	//	}
	//	return nil
	//case apis.PlatfromKubernetes:
	//	var res *meta.ScheduleResults
	//	if err := c.ScheduleResultGet(guid, &res); err != nil {
	//		return fmt.Errorf("get schedule result %v", err)
	//	}
	//	m, err := meta.DeCodeScheduleMaps(res.ScheduleMap)
	//	if err != nil {
	//		return fmt.Errorf("decode schedule map %v", err)
	//	}
	//
	//	var cells = helm.Cells{
	//		Cells: make(map[string]helm.Cell),
	//	}
	//	var agentCells = make(map[string]helm.Cells)
	//	for _, agentGuid := range m {
	//		var data = []map[string]interface{}{}
	//		if err = c.GetStatus(fmt.Sprintf(metrics_sql.K8sContainerState, guid, agentGuid, start, end), &data); err != nil {
	//			return fmt.Errorf("get data")
	//		}
	//
	//		//agentCells[agentGuid] = helm.Cells{
	//		//	Cells: make(map[string]helm.Cell),
	//		//}
	//		if _, ok := agentCells[agentGuid]; !ok {
	//			agentCells[agentGuid] = helm.Cells{
	//				Cells: make(map[string]helm.Cell),
	//			}
	//		}
	//		for _, v := range data {
	//			container := v["container"].(string)
	//			pod := v["pod"].(string)
	//			node := v["node"].(string)
	//			state := v["_value"].(string)
	//			cells.Cells[container] = helm.Cell{
	//				ContainerName: container,
	//				PodName:       pod,
	//				State:         state,
	//				Guid:          agentGuid,
	//				NodeName:      node,
	//			}
	//			agentCells[agentGuid].Cells[strings.Join([]string{guid, container}, "_")] = helm.Cell{
	//				ContainerName: container,
	//				State:         state,
	//				PodName:       pod,
	//				Guid:          guid,
	//				NodeName:      node,
	//			}
	//		}
	//	}
	//	bts, _ := json.Marshal(cells)
	//
	//	StrCell := string(bts)
	//	if _, err := c.MetaDB().Exec(`insert into instance_runtime (guid,platform,cells) values (?,?,?) on duplicate key update cells=?`, guid, platform, StrCell, StrCell); err != nil {
	//		return fmt.Errorf("save resource tree %v", err)
	//	}
	//
	//	for agentGuid, ac := range agentCells {
	//		var oldcells []meta.AgentRunTime
	//		if err = c.MetaDB().SQL(`select * from agent_runtime where guid=?`, agentGuid).Find(&oldcells); err != nil {
	//			return fmt.Errorf("save agent runtime %v", err)
	//		}
	//		var bts2 []byte
	//		var counts int
	//		if len(oldcells) != 0 {
	//			var gcell helm.Cells
	//			if err = json.Unmarshal([]byte(oldcells[0].Cells), &gcell); err != nil {
	//				return err
	//			}
	//			for k, v := range ac.Cells {
	//				gcell.Cells[k] = v
	//			}
	//			bts2, _ = json.Marshal(gcell)
	//			counts = len(gcell.Cells)
	//		} else {
	//			bts2, _ = json.Marshal(ac)
	//			counts = len(ac.Cells)
	//		}
	//		agentStrCell := string(bts2)
	//		if _, err := c.MetaDB().Exec(`insert into agent_runtime (guid,counts,cells) values (?,?,?) on duplicate key update counts=?,cells=?`, agentGuid, counts, agentStrCell, counts, agentStrCell); err != nil {
	//			return fmt.Errorf("save agent runtime %v", err)
	//		}
	//	}
	//	return nil
	default:
		return fmt.Errorf("unknown platform, must in", apis.Platforms())
	}
}

func GetInstanceContainerAndState(db dbi.GlueDB, key string) (interface{}, string, error) {
	var insRunTime *meta.InstanceRunTime
	if err := db.InstanceRuntimeGet(key, &insRunTime); err != nil {
		if errors.Is(err, gerrors.DataNotFind) {
			return nil, meta.StateUnKnown, nil
		}
		return nil, meta.StateNotReady, err
	}
	var state = meta.StateNotReady

	var containers = make(map[string]map[string]interface{})
	switch insRunTime.AppPlatform {
	case apis.PlatfromGluenets:
		cstates := strings.Split(insRunTime.Status, "|")

		//fmt.Printf("\n %v \n", cstates)

		var allReady = true
		for _, v := range cstates {
			cs := strings.Split(v, ",")
			if len(cs) == 2 {
				if cs[1] == meta.StateNotReady {
					allReady = false
				}
				containers[cs[0]] = map[string]interface{}{
					"state": cs[1],
				}
			}
		}
		cinfo := make(map[string]interface{})
		if err := json.Unmarshal([]byte(insRunTime.ContainersInfo), &cinfo); err == nil {
			for k, v := range cinfo {
				containers[k]["info"] = v
			}
		}

		if allReady && len(containers) > 0 {
			state = meta.StateReady
		}
	case apis.PlatfromKubernetes:
		cstates := strings.Split(insRunTime.Status, "|")
		var allReady = true
		for _, v := range cstates {
			cs := strings.Split(v, ",")
			if len(cs) == 2 {
				if cs[1] == meta.StateNotReady {
					allReady = false
				}
				containers[cs[0]] = map[string]interface{}{
					"state": cs[1],
				}
			}
		}
		cinfo := make(map[string]interface{})
		if err := json.Unmarshal([]byte(insRunTime.ContainersInfo), &cinfo); err == nil {
			for k, v := range cinfo {
				containers[k]["info"] = v
			}
		}
		//for _, v := range cinfo {
		//	ci := strings.Split(v, ",")
		//	if len(ci) == 4 {
		//		cts := containers[ci[0]].(map[string]interface{})
		//		cts["pod"] = ci[1]
		//		cts["machine"] = ci[2]
		//		cts["agentGuid"] = ci[3]
		//	}
		//}

		if allReady && len(containers) > 0 {
			state = meta.StateReady
		}
	}
	return containers, state, nil
}

func UpdateTrace(c dbi.GlueDB, platform string, instance *meta.Instance) error {
	end := time.Now().Unix()
	start := end - 3600*24

	switch platform {
	case apis.PlatfromGluenets:
		var irun *meta.InstanceRunTime
		if err := c.InstanceRuntimeGet(instance.Guid, &irun); err != nil {
			return err
		}

		containers := strings.Split(irun.Containers, "|")
		var cobj []string
		for _, vc := range containers {
			iv := strings.Split(vc, ",")
			cobj = append(cobj, iv[0])
		}

		var traces = make(map[string]interface{})
		if err := c.GetTracesGluenets(instance.Guid, cobj, start*1000000, end*1000000, 1, traces); err != nil {
			return err
		}
		if len(traces) == 0 {
			return nil
		}

		bts, _ := json.Marshal(traces)
		if err := c.InstanceRuntimeContainerTracesUpdate(instance.Guid, string(bts)); err != nil {
			return err
		}
	case apis.PlatfromKubernetes:
		var traces = make(map[string]interface{})
		if err := c.GetTracesK8s(instance.Guid, start*1000000, end*1000000, 1, traces); err != nil {
			return err
		}
		if len(traces) == 0 {
			return nil
		}

		bts, _ := json.Marshal(traces)
		if err := c.InstanceRuntimeContainerTracesUpdate(instance.Guid, string(bts)); err != nil {
			return err
		}
	}
	return nil
}
